#!/usr/bin/env python
# USP Websites Plugin Version 1.0
##Description:Firefox/Mozilla Bookmarks
try:
    import pygtk
    pygtk.require( "2.0" )
except:
    pass

import gtk
import gtk.glade
import sys
import os
import gobject
import gconf
import pango

from easyfiles import *
from easybuttons import *
from execute import *
from easygconf import *

class TreeViewTooltips:

    def __init__(self):
        
        # create the window
        self.window = window = gtk.Window(gtk.WINDOW_POPUP)
        window.set_name('gtk-tooltips')
        window.set_resizable(False)
        window.set_border_width(4)
        window.set_app_paintable(True)
        window.connect("expose-event", self.__on_expose_event)


        # create the label
        self.label = label = gtk.Label()
        label.set_line_wrap(True)
        label.set_alignment(0.5, 0.5)
        label.set_use_markup(False)
        label.show()
        window.add(label)

        # by default, the tooltip is enabled
        self.__enabled = True
        # saves the current cell
        self.__save = None
        # the timer id for the next tooltip to be shown
        self.__next = None
        # flag on whether the tooltip window is shown
        self.__shown = False

    def enable(self):
        self.__enabled = True
        
    def disable(self):
        self.__enabled = False

    def __show(self, tooltip, x, y):

        window = self.window
        
        # set label
        self.label.set_label(tooltip)
        # resize window
        w, h = window.size_request()
        # move the window 
        window.move(*self.location(x,y,w,h))
        # show it
        window.show()
        self.__shown = True

    def __hide(self):
        'hide the tooltip'

        self.__queue_next()
        self.window.hide()
        self.__shown = False

    def __leave_handler(self, view, event):
        'when the pointer leaves the view, hide the tooltip'
        
        self.__hide()

    def __motion_handler(self, view, event):
        'As the pointer moves across the view, show a tooltip.'

        path = view.get_path_at_pos(int(event.x), int(event.y))
        
        if self.__enabled and path:
            path, col, x, y = path
            tooltip = self.get_tooltip(view, col, path)
            if tooltip is not None:
                tooltip = str(tooltip).strip()
                if tooltip:
                    self.__queue_next((path, col), tooltip,
                                      int(event.x_root),
                                      int(event.y_root))
                    return

        self.__hide()

    def __queue_next(self, *args):

        'queue next request to show a tooltip'

        # if args is non-empty it means a request was made to show a
        # tooltip.  if empty, no request is being made, but any
        # pending requests should be cancelled anyway.

        cell = None

        # if called with args, break them out
        if args:
            cell, tooltip, x, y = args

        # if it's the same cell as previously shown, just return
        if self.__save == cell:
            return

        # if we have something queued up, cancel it
        if self.__next:
            gobject.source_remove(self.__next)
            self.__next = None

        if cell:
            # if the tooltip is already shown, show the new one
            # immediately
            if self.__shown:
                self.__show(tooltip, x, y)
            # else queue it up in 1/10 second
            else:
                self.__next = gobject.timeout_add(100, self.__show,
                                                  tooltip, x, y)

        # save this cell
        self.__save = cell


    def __on_expose_event(self, window, event):
        w, h = window.size_request()
        window.style.paint_flat_box(window.window, gtk.STATE_NORMAL,gtk.SHADOW_OUT, None, window,'tooltip', 0, 0, w, h)

    def location(self, x, y, w, h):
        return x - w/2, y + 4

    def add_view(self, view):
        assert isinstance(view, gtk.TreeView), \
               ('This handler should only be connected to '
                'instances of gtk.TreeView')
        view.connect("motion-notify-event", self.__motion_handler)
        view.connect("leave-notify-event", self.__leave_handler)

class WebTips(TreeViewTooltips):

        def __init__(self, column):
            self.col = column
            TreeViewTooltips.__init__(self)

        def get_tooltip(self, view, column, path):
            if column is self.col:
                model = view.get_model()
                tiptoshow = model[path][1]
                return '%s' % tiptoshow

class pluginclass:
	TARGET_TYPE_TEXT = 80
	toButton = [ ( "text/uri-list", 0, TARGET_TYPE_TEXT ) ]
	"""This is the main class for the plugin"""
	"""It MUST be named pluginclass"""
	def __init__(self, USPWin):

		self.USPWin = USPWin

		#The Glade file for the plugin
		self.gladefile = os.path.join(os.path.dirname(__file__), "internet.glade")

		#Read GLADE file
		self.wTree = gtk.glade.XML(self.gladefile,"window1")

		#These properties are NECESSARY to maintain consistency
		#throughout USP

		#Set 'window' property for the plugin (Must be the root widget)
		self.window = self.wTree.get_widget("window1")

		#Set 'heading' property for plugin
		self.heading = "Internet"

		#This should be the first item added to the window in glade
		self.content_holder = self.wTree.get_widget("eventbox1")

		# Items in the Glade file to get custom colors, store in an array
		self.itemstocolor = [self.wTree.get_widget('vbox1'),self.wTree.get_widget('scrolledwindow1'),self.wTree.get_widget('viewport1'),self.wTree.get_widget('BookmarksList')]

		#Specify plugin width
		self.width = 250

		#Plugin icon
		self.icon = 'mozilla-firefox.png'

		# GConf stuff notify_add will call RegenPlugin if one of the listed gconf entries is changed.
		self.gconf_dir = '/apps/usp/plugins/internet'
		self.client = gconf.client_get_default()
		self.client.add_dir('/apps/usp/plugins/internet', gconf.CLIENT_PRELOAD_NONE)
		self.client.notify_add('/apps/usp/plugins/internet/sticky',self.RegenPlugin)
		self.client.notify_add('/apps/usp/plugins/internet/icon',self.RegenPlugin)
		self.client.notify_add('/apps/usp/plugins/internet/bookmark_file',self.RegenPlugin)
		self.client.notify_add('/apps/usp/plugins/internet/height',self.RegenPlugin)
		self.client.notify_add('/apps/usp/plugins/internet/width',self.RegenPlugin)
		self.client.notify_add('/apps/usp/plugins/internet/internet_font_size',self.RegenPlugin)
		#self.client.notify_add('/apps/usp/plugins/internet/back_color',self.RegenPlugin)
		#self.client.notify_add('/apps/usp/plugins/internet/font_color',self.RegenPlugin)
		#self.client.notify_add('/apps/usp/custom_color',self.RegenPlugin)

		self.FileList=[]

		self.RegenPlugin()

		self.wTree.get_widget("window1").set_size_request(self.height,self.width)
		#Connect event handlers
		dic = { "on_window1_destroy" : gtk.main_quit,
				"on_BookmarksList_row_activated" : self.callback}
		self.wTree.signal_autoconnect(dic)

	def RegenPlugin(self, *args, **kargs):
		self.GetGconfEntries()
		self.DoWeb()
		self.tips = WebTips(self.column)
		self.tips.add_view(self.wTree.get_widget("BookmarksList"))
		self.width=self.webw

	def GetGconfEntries(self):
		# Get USP required GConf entries------------------#
		self.client = gconf.client_get_default()
		self.height = SetGconf(self.client,'int','/apps/usp/plugins/internet/height',200)
		self.width = SetGconf(self.client,'int','/apps/usp/plugins/internet/width',250)
		# Allow plugin to be minimized to the left plugin pane
		self.minimized = SetGconf( self.client, "bool", "/apps/usp/plugins/internet/minimized", False )
		self.sticky = SetGconf( self.client, "bool", "/apps/usp/plugins/internet/sticky", False )
		# Icon for the plugin
		self.icon = SetGconf( self.client, "string", '/apps/usp/plugins/internet/icon', "mozilla-firefox.png" )
		# End of USP required GConf entries---------------#
		self.bookfile = SetGconf(self.client,'string','/apps/usp/plugins/internet/bookmark_file',"")
		self.webh = self.height-10
		self.webw = self.width-10
		self.webfontsize = SetGconf(self.client,'int','/apps/usp/plugins/internet/internet_font_size', 9)
		#self.backcolor = SetGconf(self.client,'string','/apps/usp/plugins/internet/back_color',"#d4d4d4")
		#self.fontcolor = SetGconf(self.client,'string','/apps/usp/plugins/internet/font_color',"#000000")
		#self.customcolor = SetGconf(self.client,'string','/apps/usp/custom_color',"#d4d4d4")

	def SetHidden( self, state ):
		if state == True:
			WriteGconf( self.client, "bool", "/apps/usp/plugins/internet/minimized", True )
		else:
			WriteGconf( self.client, "bool", "/apps/usp/plugins/internet/minimized", False )

	def DoWeb(self, *args, **kargs):
		self.renderer = gtk.CellRendererText()
		#self.renderer.set_property("cell-background",self.backcolor)
		self.renderer.set_property("size",self.webfontsize*1000)
		#self.renderer.set_property("foreground",self.fontcolor)
		self.column = gtk.TreeViewColumn("Bookmarks")
		self.treestore = gtk.TreeStore(str,str,str)

		#Need to remove old column before new one if this is regenerated or we get multiple columns.
		if len(self.wTree.get_widget("BookmarksList").get_columns()) > 0:
			self.wTree.get_widget("BookmarksList").remove_column(self.wTree.get_widget("BookmarksList").get_column(0))

		self.wTree.get_widget("BookmarksList").append_column(self.column)
		self.column.pack_start(self.renderer, True)
		self.column.add_attribute(self.renderer, 'text', 0)
		n=len(self.wTree.get_widget("BookmarksList").get_children())-1
		while n >= 0:
			self.wTree.get_widget("BookmarksList").remove(self.wTree.get_widget("BookmarksList").get_children()[n])
			n-=1
		os.chdir(os.path.expanduser("~"))
		self.FileList=self.GetWeb()
		if self.USPWin.VERBOSE == True:
			print "\nFileList\n-------------------"
			for item in self.FileList:
				print item[0]
		self.wTree.get_widget("viewport1").set_size_request(self.webw,self.webh)
		self.wTree.get_widget("BookmarksList").set_size_request(-1,-1)
		#items=["eventbox1","vbox1","scrolledwindow1","viewport1","BookmarksList"]
		#i=0	
		#while i < len(items):
		#	self.wTree.get_widget(items[i]).modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.customcolor))
		#	i+=1
		self.wTree.get_widget("BookmarksList").set_model(self.treestore)
		self.wTree.get_widget("BookmarksList").show()
		return True

	def callback(self, widget, *args,**kargs):
		ItemInfo = self.treestore.get(widget.get_selection().get_selected()[1],0,1,2)
		if ItemInfo[2]=='URL':
			self.USPWin.wTree.get_widget("window1").hide()
			os.system("gnome-open \""+ItemInfo[1]+"\" &")
			print "Opening URL \""+ItemInfo[1]+"\""
			self.wTree.get_widget("BookmarksList").collapse_all()
			widget.get_selection().unselect_all()

	def GetWeb(self, *args, **kargs):
		os.chdir(os.path.expanduser("~"))
		Error_Message=""
		TempArray=[]	
		pathwordlen=len("Path=")
		foldername=""
		self.myiter=self.treestore.get_iter_root()
		if self.bookfile == "":
			try:
				in_file = open(".mozilla/firefox/profiles.ini","r")
				pathwordlen=len("Path=")
				foldername=""
				done=False
				while not done:
					FileLine=in_file.readline()
					if FileLine == -1:
						done=True
					else:
						if FileLine.find("Path=")!= -1:
							foldername=FileLine[pathwordlen:-1]
							done=True
				in_file.close()
				if foldername != "":
					try:
						in_file = open(".mozilla/firefox/"+foldername+"/bookmarks.html","r")
						self.client.set_string("/apps/usp/plugins/internet/bookmark_file",os.path.expanduser("~")+"/.mozilla/firefox/"+foldername+"/bookmarks.html")
					except:
						Error_Message="bookmarks.html error"
						pass
			except:
				Error_Message="profiles.ini error"
				pass
		else:
			try:
				in_file = open(self.bookfile,"r")
			except:
				Error_Message=self.bookfile+" error"
				pass
		if Error_Message == "":
			ItemCount=0
			done=False
			TextLen = len('<A HREF="')
			SubMenuName=""
			self.myiter=self.treestore.get_iter_root()
			while not done:
				FileLine=in_file.readline()
				if FileLine == "":
					done=True
				else:
					IsSubMenu=FileLine.find('<DL>')
					if IsSubMenu != -1:
						Found=False
						while Found == False:
							FileLine=in_file.readline()
							if FileLine == "":
								done=True
								break
							StartPoint=FileLine.find("<H3 ")
							if  StartPoint != -1:
								Found=True
								StartPoint=FileLine.find(">",StartPoint+1)
								EndPoint=FileLine.find("</H3>")
								Paired=[FileLine[StartPoint+1:EndPoint],"["+FileLine[StartPoint+1:EndPoint]+"]",SubMenuName+"/"+FileLine[StartPoint+1:EndPoint],'FOLDER']
								SubMenuName=SubMenuName+"/"+FileLine[StartPoint+1:EndPoint]
								self.myiter = self.treestore.append(self.myiter, [Paired[1],Paired[0],Paired[2]])
								ItemCount+=1	
								TempArray.append(Paired)
							StartPoint=FileLine.find('<A HREF="')
							if StartPoint != -1:
								Paired=[]
								EndPoint=FileLine.find('" ',StartPoint)
								DescStart=FileLine.find('>',EndPoint)
								DescEnd=FileLine.find('</A>',DescStart)
								Paired=[FileLine[StartPoint+TextLen:EndPoint],FileLine[DescStart+1:DescEnd],"URL",SubMenuName]
								self.treestore.append(self.myiter, [Paired[1], Paired[0], Paired[2]])
								#self.RecentTips.set_tip( self.myiter, Paired[1], tip_private=None )
								ItemCount+=1
								TempArray.append(Paired)
							EndSubMenu=FileLine.find('</DL>')
							if EndSubMenu != -1:
								point = SubMenuName[:-1].rfind("/")
								SubMenuName=SubMenuName[:point]
								if self.myiter != None:
									self.myiter=self.treestore.iter_parent(self.myiter)
			in_file.close()
		else:
			print Error_Message
			self.myiter=self.treestore.get_iter_root()
			self.treestore.append(self.myiter,[Error_Message,Error_Message,Error_Message])
			TempArray=[]
		return TempArray

#---------------------------------------------------------------------------------------#
# USPconfig Section Below
#---------------------------------------------------------------------------------------#
# This is the Config Class it must be called "cfgpluginclass'
class cfgpluginclass:
	def __init__(self):
		# The Gladefile for the plugins USPconfig Tab
		self.gladefile = os.path.join(os.path.dirname(__file__), "internet.glade")
		# Read GLADE file
		self.wTree = gtk.glade.XML(self.gladefile,"config")
		# Set 'window' property for the plugin (Must be the root widget)
		self.window = self.wTree.get_widget("config")
		# Content Place Holder must be eventbox2
		self.content_holder = self.wTree.get_widget("eventbox2")
		# Set Heading, this will be used for the tab label in USPconfig
		self.heading = "Internet"
		# GConf Stuff - This just makes sure a gconf path is there.
		self.gconf_dir = '/apps/usp/plugins/internet'
		self.client = gconf.client_get_default()
		self.client.add_dir('/apps/usp/plugins/internet', gconf.CLIENT_PRELOAD_NONE)
		# Setup the Functions of the Glade files spin controls or entry boxes for Value Changes
		# Tip: For spinbutton controls use the "_value_changed" event not the "_changed" event.
		dic = { "on_window2_destroy" : gtk.main_quit,
				"on_StickyChkBtn_toggled" : self.sticky,
				"on_WebIconEntry_changed" : self.icon_changed,
				"on_WebEntry_changed" : self.webentry,
				"on_WebFontSpin_changed" : self.webfontspin,
				"on_WebHSpin_changed" : self.webhspin,
				"on_WebWSpin_changed" : self.webwspin}
		self.wTree.signal_autoconnect(dic)
		# Read Values from GConf for USPconfig Tab and Set Default Values in GConf if they don't exist.
		self.wTree.get_widget("StickyChkBtn").set_active(SetGconf(self.client,'bool','/apps/usp/plugins/internet/sticky',False))
		self.wTree.get_widget("WebIconEntry").set_text(SetGconf( self.client, "string", '/apps/usp/plugins/internet/icon', "computer.png"))
		self.wTree.get_widget("WebEntry").set_text(SetGconf(self.client,'string','/apps/usp/plugins/internet/bookmark_file',''))
		self.wTree.get_widget("WebFontSpin").set_value(SetGconf(self.client,'int','/apps/usp/plugins/internet/internet_font_size',9))
		self.wTree.get_widget("WebWSpin").set_value(SetGconf(self.client,'int','/apps/usp/plugins/internet/width',200))
		self.wTree.get_widget("WebHSpin").set_value(SetGconf(self.client,'int','/apps/usp/plugins/internet/height',200))

	# Functions for Changing Values when items checked or altered.
	def sticky(self, *args, **kargs):
		if self.wTree.get_widget("StickyChkBtn").get_active() == True:
			self.client.set_bool('/apps/usp/plugins/internet/sticky',True)
		else:
			self.client.set_bool('/apps/usp/plugins/internet/sticky',False)

	def icon_changed(self, *args, **kargs):
		self.client.set_string('/apps/usp/plugins/internet/icon',self.wTree.get_widget("WebIconEntry").get_text())

	def webentry(self, widget, **kargs):
		self.client.set_string('/apps/usp/plugins/internet/bookmark_file',self.wTree.get_widget("WebEntry").get_text())

	def webfontspin(self, widget, **kargs):
		self.client.set_int('/apps/usp/plugins/internet/internet_font_size',int(self.wTree.get_widget("WebFontSpin").get_value()))

	def webhspin(self, widget, **kargs):
		self.client.set_int('/apps/usp/plugins/internet/height',int(self.wTree.get_widget("WebHSpin").get_value()))

	def webwspin(self, widget, **kargs):
		self.client.set_int('/apps/usp/plugins/internet/width',int(self.wTree.get_widget("WebWSpin").get_value()))

